using System;
using System.Collections.Generic;
using App_Code.Context;
using dbvc.context.Project;
using dbvc.context.Script;
using dbvc.context.Security;
using dbvc.context.Version;
using dbvc.data;
using dbvc.Queries;
using WGT;
using System.Linq;

namespace App_Code
{
    public abstract class Editor<T> : Dialog
    {
        protected Func<T> Model;

        protected void Init(int w, int h, string theme, Func<T> state)
        {
            Model = state;
            Init(w, h, theme);
        }
    }
    
    public class dbvc_main: Editor<dbvc_model>
    {
        private enum Popups
        {
            None,
            Project,
            User,
            Tag,
            ProjectUser,
            Version,
            Script
        }
        
        private string login = "root";
        private string passw = "root";
        
        private Popups _currPopup = Popups.None;
        
        private string projectName = "NO_NAME";
        private bool projectActive = true;

        private string tagName = "NO_NAME";

        private DateTime versionDate = DateTime.Now;
        private string versionName;
        
        public dbvc_main(int width, int height, string theme, Func<dbvc_model> state)
        { 
            Init(width-25, height-45, theme, state);
        }

        // shortcut
        private db_user Principal
        {
            get { return Model().Security.Principal; }
        }

        protected string Cookies
        {
            get; set;
        }

        protected Column[] Script_Columns
        {
            get
            {
                return new[]
                     {
                         new Column(){Name = "", Sort = "", Width = 50},
                         //new Column(){Name = "#", Sort = "", Width = 30},
                         new Column(){Name = "ID", Sort = "id", Width = 35},
                         new Column(){Name = "NAME", Sort = "name", Width = 310},
                         new Column(){Name = "AUTHOR", Sort = "userstamp", Width = 260},
                         new Column(){Name = "TAGS", Sort = "tags", Width = 260},
                     };
            }
        }

        protected Column[] UsersManager_Columns
        {
            get
            {
                return new[]
                     {
                         new Column(){Name = "", Sort = "", Width = 20},
                         new Column(){Name = "Name", Sort = "", Width = 150},
                         new Column(){Name = "Login", Sort = "", Width = 100},
                         new Column(){Name = "Password", Sort = "", Width = 164},
                     };
            }
        }

        #region | SHARED |

        private void OpenPopup(Action content, int w, int h)
        {
            Panel(pos((Width - w) / 2, (Height - h) / 2, w + 20, h + 20),
                () =>
                {
                    deEndHorizontal(10);
                    deVerticalShift(10);
                    content();
                }, null, "popup");
        }

        private void ClosePopup()
        {
            _currPopup = Popups.None;
        }

        private void Pager(IQuery query, int h)
        {
            int i = 1;
            deStartHorizontal();
            FOR(() => i, () => i <= query.PageCount, () => i++,
                () =>
                {
                    var css = "";
                    if (query.PageIndex == i) css = "clm";
                    if (Button(Size(20, h), i.ToString(), null, css))
                    {
                        if (query.PageIndex != i) query.Goto(i);

                        DD_THROW();
                    }
                });
            deEndHorizontal(h);
        }

        public void Header<T>(T query, Column[] columns, int h) where T : IQuery
        {
            deStartHorizontal();

            int i = 0;
            FOR(() => i, () => i < columns.Length, () => i++,
                () =>
                {
                    var clm = columns[i];
                    var css = "clm";

                    if (clm.Sort == query.Sort) css += query.IsAsc ? "_asc" : "_desc";

                    if (Button(Size(clm.Width, h), clm.Name, null, css))
                    {
                        if (!string.IsNullOrEmpty(clm.Sort))
                            query.SortBy(clm.Sort);

                        DD_THROW();
                    }

                });
            deEndHorizontal(33);
        }

        #endregion

        public override void View()
        {
            // block panel
            Panel( pos(0, 0, Width + 10, Height + 40), null, (_currPopup != Popups.None).ToVisible(), "blank" );
            
            gx = 5; gy = 5;

            Action content = () => IF(() => Model().Security.IsAuth(), Main, Login);

            // popup container
            Panel( pos(0, 0, 0, 0), () => 
                SWITCH(_currPopup,
                   new Dictionary<Popups, Action>{
                        {Popups.Project,      () => OpenPopup(Project, 250, 100)}
                       ,{Popups.User,         () => OpenPopup(User, 440, 350)}
                       ,{Popups.Tag,          () => OpenPopup(Tag, 250, 100)}
                       ,{Popups.ProjectUser,  () => OpenPopup(ProjectUser, 700, 500)}
                       ,{Popups.Script,       () => OpenPopup(Script, 750, 650)}
                       ,{Popups.Version,      () => OpenPopup(Version, 200, 70)}
                   }), null, "hold");

            // main container
            Panel( Size(Width, Height), content );
        }

        private void Main()
        {
            Panel(pos((Width - 1024) / 2, (Height - 768) / 2, 1024, 768),
              () =>
                  {
                      deEndHorizontal(20);
                      deVerticalShift(20);

                      #region | TOOLBAR |

                      deStartHorizontal();

                      if (Button(Size(60, 25), "Logout", null))
                      {
                          Model().Security.Logout();

                          DD_THROW();
                      }

                      deVerticalShift(3);

                      if (Img(Size(30, 30), "project.png".ToActionImage(Theme), null))
                      {
                          _currPopup = Popups.Project;

                          DD_THROW();
                      }

                      deVerticalShift(3);

                      if (Img(Size(30, 30), "usr.png".ToActionImage(Theme), null))
                      {
                          Model().qUser.Execute();
                          _currPopup = Popups.User;

                          DD_THROW();
                      }

                      deVerticalShift(3);

                      if (Img(Size(30, 30), "tag.png".ToActionImage(Theme), null))
                      {
                          _currPopup = Popups.Tag;

                          DD_THROW();
                      }
                      
                      //Static(Size(100, 20), () => Model().Security.Principal.name, null);
                      
                      deEndHorizontal(40); 
                      #endregion

                      #region | FILTER |

                      deStartHorizontal();
                      Static(Size(100, 20), () => "Current Project: ", null);

                      if (DropDown(
                          Size(150, 18),
                          () => ProjectQuery.GetUserProjects(Model().Security.Principal.id),
                          (p) => p.id.ToString(),
                          (p) => p.name,
                          (p) => Model().Project = Int32.Parse(p),
                          Model().Project.ToString(),
                          null))
                      {
                          DD_THROW();
                      }

                      deVerticalShift(3);

                      if (Img(Size(16, 16), "group.png".ToActionImage(Theme), null))
                      {
                          Model().qUser.Execute();
                          _currPopup = Popups.ProjectUser;

                          DD_THROW();
                      }

                      deVerticalShift(3);

                      if (Img(Size(16, 16), "version.png".ToActionImage(Theme), null))
                      {
                          _currPopup = Popups.Version;

                          DD_THROW();
                      }

                      deVerticalShift(3);

                      if (Img(Size(16, 16), "journal.png".ToActionImage(Theme), null))
                      {
                          throw new NotImplementedException();

                          DD_THROW();
                      }

                      deVerticalShift(3);

                      if (Img(Size(16, 16), "generate.png".ToActionImage(Theme), null))
                      {
                          throw new NotImplementedException();

                          DD_THROW();
                      }

                      deEndHorizontal(26);

                      deStartHorizontal();

                      //deVerticalShift(15);

                      Static(Size(100, 20), () => "Version: ", null);
                      if (DropDown(
                          Size(150, 18),
                          () => VersionQuery.GetVersions(Model().Project),
                          (p) => p.id.ToString(),
                          (p) => p.name,
                          (p) => Model().Version = Int32.Parse(p),
                          Model().Version.ToString(),
                          Model().Project.ToString()))
                      {
                          DD_THROW();
                      }

                      deEndHorizontal(32);
 
                      #endregion

                      #region | GRID |

                      Static(Size(80, 40), () => "<h2>SCRIPTS</h2>", null);

                      deStartHorizontal();

                      if (Button(Size(60, 25), "Add", (Model().Version == 0).ToEnabled()))
                      {
                          Model().Script = 0;
                          _currPopup = Popups.Script;
                          DD_THROW();
                      }

                      deEndHorizontal(32);

                      Header(Model().qScript, Script_Columns, 30);

                      int i = 0;
                      FOR(() => i, () => i < Model().qScript.Records.Count(), () => i++,
                        () =>
                        {

                            deStartHorizontal();

                            db_script p = P(() => Model().qScript.Records[i]);

                            if (Img(Size(20, 20), "del_s.png".ToActionImage(Theme), null))
                            {
                                //Model().qScripts.Records.RemoveAt(i); 
                                DD_THROW();
                            }

                            deVerticalShift(2);

                            if (Img(Size(20, 20), "edit_s.png".ToActionImage(Theme), null))
                            {
                                Model().Script = p.id;
                                _currPopup = Popups.Script;
                                DD_THROW();
                            }

                            deVerticalShift(12);

                            Static(Size(35, 20), () => p.id.ToString(), null);
                            Static(Size(310, 20), () => "<b>" + p.name + "</b>", null);
                            Static(Size(260, 20), () => "<i>" + p.userstamp + "</i>", null);
                            Static(Size(260, 20), () => "<i>" + p.tags + "</i>", null);

                            //Edit(Size(35, 20), () => p.id.ToString(), null, null);
                            //Edit(Size(310, 20), () => "<b>" + p.name + "</b>", null, null);
                            //Edit(Size(260, 20), () => "<i>" + p.userstamp + "</i>", null, null);
                            //Edit(Size(260, 20), () => "<i>" + p.tags + "</i>", null, null);

                            deEndHorizontal(22);
                        });

                      deStartHorizontal();
                      deEndHorizontal(5);

                      Pager(Model().qScript, 25);
 
                      #endregion

                  }, null, "wnd");
        }

        private void Project()
        {
            deStartHorizontal();
                Static(pos(20, 30, 50, 20), () => "Name:", null);
                Edit(pos(70, 30, 150, 16), () => projectName, (s) => projectName = s, null);
            deEndHorizontal(23);

            //deStartHorizontal();
            //    CheckBox(Size(20, 20), () => projectActive, (a) => projectActive = a, null);
            //    Static(Size(100, 20), () => "Active", null);
            //deEndHorizontal(23);
            
            deStartHorizontal();
                if ( Button(pos(130, 60, 50, 25), "Save", null) )
                {
                    new CreateProject(Principal, new db_project() { name = projectName, active = projectActive }).Execute();
                    ClosePopup();
                    DD_THROW();
                }

                if (Button(pos(184, 60, 50, 25), "Cancel", null)) { ClosePopup(); DD_THROW(); }
            deEndHorizontal(23);
        }

        private void User()
        {
            deStartHorizontal();
                Static(pos(20, 20, 50, 20), () => "User:", null);
                Edit(pos(60, 20, 150, 16), () => tagName, (s) => tagName = s, null);

                if (Button(pos(220, 20, 33, 20), "Add", null))
                {
                    DD_THROW();
                }
            deEndHorizontal(40);

            int y = 0;
            int count = Model().qUser.Records.Count();

            deStartHorizontal();

            Header(Model().qScript, UsersManager_Columns, 30);

            FOR(() => y, () => y < count, () => y++,
                () =>
                {
                    deStartHorizontal();

                    db_user p = P(() => Model().qUser.Records[y]);

                    if (CheckBox(Size(20, 20), () => projectActive, (a) => projectActive = a, null))
                    {
                        DD_THROW();
                    }

                    Edit(Size(150, 20), () => p.id.ToString(), null, null);
                    Edit(Size(100, 20), () => p.name, null, null);
                    Edit(Size(160, 20), () => p.pass, null, null);
                    
                    deEndHorizontal(20);
                });

            deEndHorizontal(35);

            deStartHorizontal();
            if (Button(Size(50, 25), "Save", null))
            {
                ClosePopup();
                DD_THROW();
            }
            deVerticalShift(4);
            if (Button(Size(50, 25), "Cancel", null)) { ClosePopup(); DD_THROW(); }
            deEndHorizontal(23);
        }

        private void Tag()
        {
            deStartHorizontal();
                Static(pos(35, 30, 40, 20), () => "Tag:", null);
                Edit(pos(70, 30, 150, 16), () => tagName, (s) => tagName = s, null);
            deEndHorizontal(23);

            deStartHorizontal();
                if (Button(pos(130, 60, 50, 25), "Save", null))
                {
                    ClosePopup();
                    DD_THROW();
                }

                if (Button(pos(184, 60, 50, 25), "Cancel", null)) { ClosePopup(); DD_THROW(); }
            deEndHorizontal(23);
        }

        private void ProjectUser()
        {
            //babel
            deEndHorizontal(10);
            deVerticalShift(10);
            deStartHorizontal();

            int y = 0;
            int count = Model().qUser.Records.Count();
            int columnCount = 3;
            int rowCount = (count + columnCount - 1)/columnCount;

            FOR(() => y, () => y < rowCount, () => y++,
              () =>
              {
                  deStartHorizontal();

                  int x = 0;
                   FOR(() => x, () => x < columnCount, () => x++,
                       () =>
                       {
                          int ind = x * rowCount + y;
                          if(ind < count)
                          {
                                db_user p = P(() => Model().qUser.Records[ind]);

                                if(CheckBox(Size(20, 20), () => projectActive, (a) => projectActive = a, null))
                                {
                                    DD_THROW();
                                }
                                Static(Size(140, 20), () => p.name, null);
                          }
                       });

                  deEndHorizontal(22);
              });

            deEndHorizontal(30);
            deStartHorizontal();
            if (Button(Size(50, 25), "Save", null))
            {
                new CreateProject(Principal, new db_project() { name = projectName, active = projectActive }).Execute();
                ClosePopup();
                DD_THROW();
            }
            deVerticalShift(4);
            if (Button(Size(50, 25), "Cancel", null)) { ClosePopup(); DD_THROW(); }
            deEndHorizontal(23);
        }

        private void Script()
        {
            //babel
            deEndHorizontal(10);
            deVerticalShift(10);

            var operation = "Add";
            if (Model().Script != 0) operation = "Edit " + Model().Script;
   
            Text(Size(600, 600), () => operation, null, "");

            CheckBox(pos(640, 30, 20, 20), () => projectActive, null, null);
            Static(pos(660, 30, 100, 20), () => "create SP", null);

            CheckBox(pos(640, 50, 20, 20), () => projectActive, null, null);
            Static(pos(660, 50, 100, 20), () => "create T", null);

            CheckBox(pos(640, 70, 20, 20), () => projectActive, null, null);
            Static(pos(660, 70, 100, 20), () => "create V", null);

            CheckBox(pos(640, 90, 20, 20), () => projectActive, null, null);
            Static(pos(660, 90, 100, 20), () => "localization", null);

            CheckBox(pos(640, 110, 20, 20), () => projectActive, null, null);
            Static(pos(660, 110, 100, 20), () => "security", null);

            deStartHorizontal();
            if (Button(pos(620, 630, 50, 25), "Save", null))
            {
                var toAdd = new db_script()
                {
                    name = Guid.NewGuid().ToString(), 
                    active=true, 
                    datestamp = DateTime.Now, 
                    tags = "test", 
                    text = Guid.NewGuid().ToString()
                };
                
                new CreateScript(Principal, toAdd).Execute();
                new AttachScript(Principal, Model().Version, toAdd).Execute();

                Model().qScript.Execute();

                ClosePopup();

                DD_THROW();
            }

            if (Button(pos(675, 630, 50, 25), "Cancel", null)) 
            { 
                ClosePopup();
                DD_THROW(); 
            }

            deEndHorizontal(3);
        }

        private void Version()
        {
            deStartHorizontal();
                Static(Size(50, 20), () => "Name:", null);
                Edit(Size(140, 16), () => versionName, (s) => versionName = s, null);
            deEndHorizontal(24);
            
            deStartHorizontal();
                Static(Size(50, 20), () => "Date:", null);
                Calendar(Size(125, 16), () => versionDate, (s) => versionDate = s, null);
            deEndHorizontal(24);

            deStartHorizontal();
            if (Button(Size(50, 25), "Save", null))
            {
                new CreateVersion(
                    Model().Security.Principal,
                    Model().Project,
                    new db_version() { name = versionName, on_date = versionDate }).Execute();

                ClosePopup();
            }
            if (Button(Size(50, 25), "Close", null)) { ClosePopup(); }
            deEndHorizontal(23);
        }

        public void Login()
        {
             Action content = () =>
              {
                  deStartHorizontal();
                      Static(Size(80, 20), () => "Login:", null);
                      Edit(Size(120, 20), () => login, (l) => login = l, null);
                  deEndHorizontal(30);
                  
                  deStartHorizontal();
                      Static(Size(80, 20), () => "Password:", null);
                      Edit(Size(120, 20), () => passw, (p) => passw = p, null);
                  deEndHorizontal(30);
                  
                  if ( Button(Size(60, 25), "Login", null) )
                  {
                      Model().Security.Login(login, passw);
                      
                      DD_THROW();
                  }
              };

            OpenPopup(content, 220, 90);
        }
    }
}